import Component, { QTr, QTh } from '@teld/q-components/Table';
import { cloneDeep } from 'lodash';
import useMappingProps from 't/common/hooks/useMappingProps';
import {
  commonProps,
  fixNameSpace,
  pickOwnForBasicComponent,
} from 't/common/utils';
import {
  defineComponent,
  onMounted,
  onBeforeUnmount,
  ref,
  watch,
  computed,
  nextTick,
} from 'vue';
import styles from './index.module.scss';
import './index.scss';

export * from '@teld/q-components/Table';
import { isNil } from 'lodash';
import { useQuasar, scroll, dom } from '@teld/q-components';
import TBtnGroup from 't/basic/button-group';

import TableContent from './TableContent';
import NoDataPlaceholder from 't/bussiness/data-grid/components/no-data-placeholder.vue';

import { tableRenderFuctions } from './tableRenderFuctions';
import Tooltip from '@teld/q-components/Tooltip';
import TCheckbox from 't/basic/checkbox';
import TInnerLoading from 't/basic/inner-loading';

export default defineComponent({
  name: 'TEditTable',
  props: {
    ...commonProps,
    ...Component.props,
    dsType: {
      type: String,
      default() {
        return '';
      },
    },
    dsCDO: {
      type: String,
      default() {
        return '';
      },
    },
    ItemsDataSourceType: {
      type: String,
      default() {
        return '';
      },
    },
    disable: {
      type: Boolean,
      default() {
        return false;
      },
    },
    readonly: {
      type: Boolean,
      default() {
        return false;
      },
    },
    enableEditing: {
      type: Boolean,
      default() {
        return true;
      },
    },
    mockData: {
      type: [Object, String],
      default() {
        return null;
      },
    },
    allowSort: {
      type: Boolean,
      default() {
        return true;
      },
    },
    showRowNumber: {
      type: Boolean,
      default() {
        return false;
      },
    },
    fillMode: {
      type: String,
      default: 'auto',
    },
    operationColumnFixed: {
      type: Boolean,
      default() {
        return false;
      },
    },
    allowColumnWarp: {
      type: Boolean,
      default() {
        return false;
      },
    },
    allowColumnResizing: {
      type: Boolean,
      default() {
        return true;
      },
    },
    enableCmdCol: {
      type: Boolean,
      default() {
        return false;
      },
    },
    staticItems: {
      type: Array,
      default() {
        return [];
      },
    },
    moreConf: {
      type: Boolean,
      default() {
        return false;
      },
    },
    autoModel: {
      type: Boolean,
      default() {
        return false;
      },
    },
    moreMaxCount: {
      type: Number,
      default() {
        return 5;
      },
    },
    moreBtnIcon: {
      type: String,
      default() {
        return '';
      },
    },
    btnDropPop: {
      type: Boolean,
      default() {
        return false;
      },
    },
    columnHelpSettings: {
      type: Array,
      default() {
        return [];
      },
    },
    columnMethod: {
      type: Object,
      default() {
        return {};
      },
    },
    beforeSave: {
      type: Function,
    },
    visible: {
      type: Boolean,
      default() {
        return true;
      },
    },
    height: {
      type: String,
      default() {
        return '500px';
      },
    },
    fillMarginBottom: {
      type: String,
      default() {
        return '';
      },
    },
    tabIndex: {
      type: [Number, String],
      default() {
        return 1;
      },
    },
    topBtnOption: {
      type: Array,
      default() {
        return ['1', '2', '3', '4'];
      },
    },
    virtualScroll: {
      type: Boolean,
      default() {
        return true;
      },
    },
    hoverModel: {
      type: Boolean,
      default() {
        return false;
      },
    },
  },
  emits: [
    'onSave',
    'saved',
    'actions',
    'selectionChanged',
    'rowsChanged',
    'dataSourceLoaded',
    'currentRowClick',
    'update:modelValue',
  ],
  components: {
    Tooltip,
  },
  setup(props, { attrs, emit, expose, slots }) {
    console.log('editTable');
    const refComponent = ref();
    const TableContentRef = ref();
    const refRoot = ref(null);
    let currentClickRowData = null;
    const [mappingProps, mappingExpose] = useMappingProps(props, {
      editComponentsRef(key, index) {
        if (key) {
          if (index != null && index != undefined && index > -1) {
            return componetsRef[key + '_' + index];
          } else {
            let obj = {};
            for (let i in componetsRef) {
              if (i.indexOf(key) > -1) {
                obj[i] = componetsRef[i];
              }
            }
            return obj;
          }
        }
        return componetsRef;
      },
      scrollTo() {
        refComponent.value.scrollTo(...arguments);
      },
      addRow(data, index) {
        addRows(data, index);
      },
      removeSelectedRowsByIndex(index) {
        deleteRowByIndex(index);
      },
      removeSelectedRows() {
        btnGroupItemClick({ value: 'delete' });
      },
      deleteRowByData(data) {
        if (data && data.length > 0) {
          if (mappingProps.dsType === 'cdo' && mappingProps.dsCDO) {
            cdoDeleteMethod(data);
          }
        }
      },
      setData(newVal) {
        tableRows.value = Array.isArray(newVal) ? newVal : [];
        orignRows = cloneDeep(newVal);
        nextTick(() => {
          emit('dataSourceLoaded');
        });
      },
      getData() {
        return [...tableRows.value];
      },
      getDataByIndex(index) {
        return tableRows.value[index];
      },
      getSelectedData() {
        return getSelectedTableData();
      },
      moveUp(i) {
        if (i) {
          upRowByIndex(i);
        } else {
          let selectedRows = getSelectedTableData();
          if (selectedRows && selectedRows.length > 0) {
            let index = selectedRows[0].rowIndex;
            upRowByIndex(index);
          } else {
            Funcs.Notify(
              $q.lang.editTable?.tips,
              $q.lang.editTable?.selectRow,
              'warning',
            );
          }
        }
      },
      moveDown(i) {
        if (i) {
          downRowByIndex(i);
        } else {
          let selectedRows = getSelectedTableData();
          if (selectedRows && selectedRows.length > 0) {
            let index = selectedRows[0].rowIndex;
            downRowByIndex(index);
          } else {
            Funcs.Notify(
              $q.lang.editTable?.tips,
              $q.lang.editTable?.selectRow,
              'warning',
            );
          }
        }
      },
      cancelEditData() {
        tableReset();
      },
      saveEditData() {
        tableSave();
      },
      saveValidataResult() {
        return saveValidata();
      },
      setColumnIsRequired(field, val) {
        let column = tableColumns.value.find(item => {
          return (
            item.field === field ||
            item.name === field ||
            item.dataField === field
          );
        });
        if (column) {
          column.isRequired = val;
        }
      },
      changeColumnName(field, val) {
        let column = tableColumns.value.find(item => {
          return (
            item.field === field ||
            item.name === field ||
            item.dataField === field
          );
        });
        if (column) {
          column.label = val;
          column.caption = val;
          makeData(mappingProps, tableRows, tableColumns, inDesign);
          //是否需要开启选择模式
          checkModel(mappingProps, tableColumns);
          showRowNumber(mappingProps, tableColumns);
          changeRowsIndex(mappingProps, tableColumns);
          rowOperation(mappingProps, tableColumns);
          allowSort(mappingProps, tableColumns);
        }
      },
      currentClickRowData() {
        return currentClickRowData;
      },
      setCheckAll(val) {
        allChecked.value = val;
      },
      setOperationBtnByCode(code, kay, val) {
        let target = mappingProps.staticItems?.find(item => {
          return item.code === code;
        });
        if (target && target.hasOwnProperty(key)) {
          target[key] = val;
        }
      },
    });
    const {
      makeData,
      showRowNumber,
      allowSort,
      checkModel,
      changeRowsIndex,
      rowOperation,
    } = tableRenderFuctions();

    let $q = useQuasar();
    let tableRows = ref([]);
    let tableColumns = ref([]);
    let allChecked = ref(false);
    const inDesign = ref(!!window['fas']?.inDesign); //判断是否设计时
    //使用cdo进行修改操作时传参
    const changeTypeMapping = {
      UnChanged: 0,
      Add: 1,
      Delete: 2,
      Update: 3,
    };
    let orignRows = cloneDeep(mappingProps.rows);
    let hasInit = false;
    let focusIndex = null;
    mappingExpose.tableColumns = tableColumns.value;
    expose(mappingExpose);
    //国际化处理
    const i18nMethod = () => {
      if (!window.Funcs) {
        return;
      }
      for (let i of mappingProps.columns) {
        if (i.hasOwnProperty('ValueInfo_caption')) {
          i.caption = Funcs.GetTerms(
            i.ValueInfo_caption.ReferenceExpr,
            i.caption,
          );
        }
      }
    };
    //模拟数据或数据处理
    makeData(mappingProps, tableRows, tableColumns, inDesign);
    //是否需要开启选择模式
    checkModel(mappingProps, tableColumns);
    //显示行号
    showRowNumber(mappingProps, tableColumns);
    //是否支持换行
    changeRowsIndex(mappingProps, tableColumns);
    // 是否开启操作列;
    rowOperation(mappingProps, tableColumns);
    //是否需要排序
    allowSort(mappingProps, tableColumns);
    let initSort = mappingProps.allowSort;

    onMounted(() => {
      //组件加载完成
      hasInit = true;
      window.addEventListener('mouseup', globalMouseUp);
      refreshHeaderLayout(refRoot.value);

      // refComponent.value.$el.style.maxWidth =
      //   dom.width(refComponent.value.$el)+ 'px';
    });
    onBeforeUnmount(() => {
      window.removeEventListener('mouseup', globalMouseUp);
    });
    watch(
      () => mappingProps.enableCmdCol,
      (newVal, oldVal) => {
        rowOperation(mappingProps, tableColumns);
      },
    );
    watch(
      () => {
        return [
          mappingProps.staticItems,
          mappingProps.moreConf,
          mappingProps.autoModel,
          mappingProps.moreMaxCount,
          mappingProps.btnDropPop,
          mappingProps.moreBtnIcon,
        ];
      },
      (newVal, oldVal) => {
        if (mappingProps.enableCmdCol) {
          let operationItem = tableColumns.value.find(item => {
            return item.name === '_operation';
          });
          if (operationItem) {
            newVal[0]?.forEach(item => (item.type = 'miniText'));
            operationItem.dataSource = [...(newVal[0] ? newVal[0] : [])];
            operationItem.btnGroupOptions = {
              moreConf: newVal[1],
              autoModel: newVal[2],
              moreMaxCount: newVal[3],
              btnDropPop: newVal[4],
              moreBtnIcon: newVal[5],
            };
          }
        }
      },
      {
        deep: true,
      },
    );
    watch(
      () => mappingProps.allowColumnWarp,
      (newVal, oldVal) => {
        changeRowsIndex(mappingProps, tableColumns);
      },
    );
    watch(
      () => mappingProps.showRowNumber,
      (newVal, oldVal) => {
        showRowNumber(mappingProps, tableColumns);
      },
    );
    const dragSortModel = ref(false);
    watch(
      () => mappingProps.allowSort,
      (newVal, oldVal) => {
        if (tableColumns.value && tableColumns.value.length > 0) {
          if (!dragSortModel.value) {
            initSort = newVal;
          }
          tableColumns.value.forEach(element => {
            if (
              element.name !== '_selected' &&
              element.name !== '_operation' &&
              element.name !== 'rowNumber' &&
              element.editorType !== 'checkbox'
            ) {
              element.sortable = newVal;
            }
          });
        }
      },
    );
    watch(
      () => {
        return [mappingProps.columns, mappingProps.mockData];
      },
      (newVal, oldVal) => {
        if (
          JSON.stringify(newVal[0]) != JSON.stringify(oldVal[0]) ||
          JSON.stringify(newVal[1]) != JSON.stringify(oldVal[1])
        ) {
          makeData(mappingProps, tableRows, tableColumns, inDesign);
          //是否需要开启选择模式
          checkModel(mappingProps, tableColumns);
          showRowNumber(mappingProps, tableColumns);
          changeRowsIndex(mappingProps, tableColumns);
          rowOperation(mappingProps, tableColumns);
          allowSort(mappingProps, tableColumns);
        }
      },
    );
    let firstData = true;
    watch(
      () => mappingProps.rows,
      (newVal, oldVal) => {
        //表格加载完后触发的事件
        tableRows.value = Array.isArray(newVal) ? newVal : [];
        // tableRows.value = Array.isArray(newVal) ? [...newVal] : [];
        // 第一次赋值时保存初始值
        if (firstData) {
          orignRows = cloneDeep(tableRows.value);
          firstData = false;
        }
        nextTick(() => {
          refreshHeaderLayout(refRoot.value);
          emit('dataSourceLoaded');
        });
      },
      { deep: true },
    );
    // watch(
    //   () => tableColumns.value,
    //   (newVal, oldVal) => {
    //     debugger;
    //   },
    //   { deep: true },
    // );
    watch(
      () => tableRows.value,
      (newVal, oldVal) => {
        emit('update:modelValue', newVal);
      },
      { deep: true },
    );
    watch(
      () => mappingProps.selection,
      (newVal, oldVal) => {
        checkModel(mappingProps, tableColumns);
      },
    );

    watch(
      () => allChecked.value,
      (newVal, oldVal) => {
        if (mappingProps.selection === 'multiple') {
          if (newVal === true) {
            for (let i = 0; i < tableRows.value.length; i++) {
              tableRows.value[i]._selected = true;
            }
          }
          if (newVal === false) {
            for (let i = 0; i < tableRows.value.length; i++) {
              tableRows.value[i]._selected = false;
            }
          }
        }
      },
    );
    // 使用cdo进行修改操作
    const cdoUpdateMethod = data => {
      if (data && data.length > 0) {
        try {
          CDO.BatchEditUpdate_Async(mappingProps.dsCDO, data)
            .then(ret => {
              let newData = tableRows.value.filter(
                item => !item._$changeset || item._$changeset.ChangeType !== 2,
              );
              for (let i of newData) {
                if (i.hasOwnProperty('_$changeset')) {
                  delete i._$changeset;
                }
              }
              tableRows.value = newData;
              orignRows = cloneDeep(tableRows.value);

              Funcs.Notify(
                $q.lang.editTable?.tips,
                $q.lang.editTable?.saveSuccess,
                'success',
              );
              //触发保存后事件
              emit('saved');
            })
            .catch(ret => {
              Funcs.Notify($q.lang.editTable?.tips, ret, 'negative');
            });
          //保存修改后，就把当前表格认为是新的初始数据，并标记过修改的值重新置为null
        } catch (error) {}
      }
    };
    //cdo模式下的删除行
    const cdoDeleteMethod = dataArray => {
      let changeSet = {
        key: null,
        ChangeTypeName: 'Delete',
        ChangeType: changeTypeMapping['Delete'],
        ChangeSetItems: [],
      };
      let deleteArray = [];
      let unSavedArray = []; //新增的但还没保存的数据
      dataArray.forEach(item => {
        if (item[mappingProps.rowKey]) {
          changeSet.key = item[mappingProps.rowKey];
          item._$changeset = changeSet;
          deleteArray.push(item);
        }
        if (
          !item[mappingProps.rowKey] ||
          item._$changeset?.ChangeTypeName == 'Add'
        ) {
          unSavedArray.push(item);
        }
      });

      let unSavedArrayToDelete = unSavedArray.map(
        item => item[mappingProps.rowKey],
      );
      deleteRowByIndex(unSavedArrayToDelete);

      let deleteArrayToDelete = deleteArray.map(
        item => item[mappingProps.rowKey],
      );
      deleteRowByIndex(deleteArrayToDelete);
    };
    //取出表格数据
    const tableSave = () => {
      //保存前事件方法触发
      if (
        mappingProps.beforeSave &&
        typeof mappingProps.beforeSave === 'function'
      ) {
        let result = beforeSave();
        if (typeof result === 'boolean' && !result) {
          return;
        }
      }
      // 如果有必填则进行检验
      let validataResult = saveValidata();
      if (!validataResult) {
        return;
      }
      //如果绑定了cdo则执行cdo的批量修改方法
      if (mappingProps.dsType === 'cdo' && mappingProps.dsCDO) {
        //取出之前编辑表格时标记好的数据
        let changeData = tableRows.value.filter(item => {
          return (
            item.hasOwnProperty('_$changeset') && item._$changeset !== null
          );
        });
        // let addData = tableRows.value.filter(item => {
        //   return !item.hasOwnProperty('_$changeset');
        // });
        if (changeData.length > 0) {
          //如果存在修改数据，则执行cdo的批量修改方法
          cdoUpdateMethod([...changeData]);
        }
      } else {
        //触发外部保存事件
        emit('onSave', tableRows.value);
      }
    };
    const saveValidata = () => {
      let validataFieldList = tableColumns.value.filter(
        item =>
          (item.isRequired == 'true' || item.isRequired === true) &&
          item.editorType &&
          item.isShow,
      );
      if (validataFieldList && validataFieldList.length > 0) {
        for (let i = 0; i < validataFieldList.length; i++) {
          for (let j = 0; j < tableRows.value.length; j++) {
            let key = validataFieldList[i].name + '_' + j;
            if (
              componetsRef.hasOwnProperty(key) &&
              componetsRef[key]?.value?.validate
            ) {
              let result = componetsRef[key].value.validate();
              if (!result) {
                Funcs.Notify(
                  $q.lang.editTable?.tips,
                  $q.lang.editTable?.requiredMsg +
                    ' : ' +
                    validataFieldList[i].label,
                  'warning',
                );
                return false;
              }
            }
          }
        }
      }
      return true;
    };
    // 获取选中的数据
    const getSelectedTableData = () => {
      return tableRows.value.filter((item, index) => {
        if (item._selected) {
          item.rowIndex = index;
          return item;
        }
      });
    };
    // 获取选中的索引
    const getSelectedTableIndex = () => {
      return tableRows.value.filter((item, index) => {
        if (item._selected) {
          return index;
        }
      });
    };
    //重置表格数据
    const tableReset = () => {
      for (let i of orignRows) {
        if (i.hasOwnProperty('_$changeset')) {
          delete i._$changeset;
        }
      }
      tableRows.value = cloneDeep(orignRows);
      emit('rowsChanged', tableRows.value, 'resetEvent');
    };
    const getFocus = index => {
      nextTick(() => {
        for (let i of tableColumns.value) {
          let key = i.name + '_' + index;
          if (
            componetsRef.hasOwnProperty(key) &&
            componetsRef[key]?.value.hasOwnProperty('focus')
          ) {
            componetsRef[key].value.focus();
            return;
          }
        }
      });
    };
    // 添加行
    const addRows = (rowData, index) => {
      //cdo模式下，增加行直接调用方法
      let newRow = {};
      if (mappingProps.dsType === 'cdo' && mappingProps.dsCDO) {
        newRow = rowData ?? {};
        CDO.NewInstance(mappingProps.dsCDO, {}).then(tRecord => {
          Object.entries(tRecord).forEach(([key, value]) => {
            newRow[key] = value;
          });
          if (!newRow[mappingProps.rowKey]) {
            newRow[mappingProps.rowKey] = Funcs.Guid();
          }
          newRow._$changeset = {
            key: tRecord[mappingProps.rowKey],
            ChangeTypeName: 'Add',
            ChangeType: changeTypeMapping['Add'],
            ChangeSetItems: [],
          };
          tableRows.value.push(newRow);
          nextTick(() => {
            //设置滚动到新增行并聚焦
            refComponent.value.scrollTo(tableRows.value.length);
            // 经试验componetsRef中新增行的对象在编辑组件完全渲染后才会有值
            setTimeout(() => {
              let inputField = tableColumns.value.find(
                item => item.editorType == 'input',
              );
              let focusIndex = tableRows.value.length - 1;
              if (
                inputField &&
                componetsRef[inputField.name + '_' + focusIndex]
              ) {
                componetsRef[inputField.name + '_' + focusIndex].value.focus();
              }
            }, 100);
          });
        });
      } else {
        for (let i of tableColumns.value) {
          if (
            i.name != 'sortRow' &&
            i.name != 'rowNumber' &&
            i.name != '_operation' &&
            i.editorType !== 'btnGroup'
          ) {
            if (i.name === '_selected') {
              newRow[i.name] = false;
            } else {
              newRow[i.name] = null;
            }
          }
        }

        newRow[mappingProps.rowKey] = Funcs.Guid();
        if (rowData && typeof rowData === 'object') {
          newRow = rowData;
        }
        //标记数据，供外层手动获取数据调用cdo时使用
        newRow._$changeset = {
          key: newRow[mappingProps.rowKey],
          ChangeTypeName: 'Add',
          ChangeType: changeTypeMapping['Add'],
          ChangeSetItems: [],
        };
        if (typeof index === 'number' && index > -1) {
          tableRows.value.splice(index, 0, newRow);
          tableRows.value.forEach((item, index) => {
            item.addEdit = true;
          });
        } else {
          tableRows.value.push(newRow);
        }

        nextTick(() => {
          //设置滚动到新增行并聚焦
          refComponent.value.scrollTo(index ?? tableRows.value.length);
          // 经试验componetsRef中新增行的对象在编辑组件完全渲染后才会有值
          setTimeout(() => {
            let inputField = tableColumns.value.find(
              item => item.editorType == 'input' && !item.editableExpr,
            );
            let focusIndex = tableRows.value.length - 1;
            if (
              inputField &&
              componetsRef[inputField.name + '_' + focusIndex]
            ) {
              componetsRef[inputField.name + '_' + focusIndex].value.focus();
            }
          }, 100);
        });
      }
    };
    // 删除行
    const deleteRowByIndex = index => {
      //给删除的行打标记,供外层手动获取数据调用cdo时使用
      let changeSet = {
        key: null,
        ChangeTypeName: 'Delete',
        ChangeType: changeTypeMapping['Delete'],
        ChangeSetItems: [],
      };
      if (typeof index === 'number') {
        if (isNil(index) || index < 0) {
          return;
        }
        let deleteData = tableRows.value.splice(index, 1);
        deleteData.forEach(item => {
          if (item[mappingProps.rowKey] && !item._$changeset) {
            changeSet.key = item[mappingProps.rowKey];
            item._$changeset = changeSet;
            item._selected = false;
          }
        });
        //触发表格列change事件
        emit('rowsChanged', deleteData, 'deleteEvent');
      }
      if (Array.isArray(index)) {
        let deleteData = [];
        if (index.length === 0) {
          return;
        }
        for (let rowkey of index) {
          if (rowkey) {
            let index = tableRows.value.findIndex(
              item => item[mappingProps.rowKey] === rowkey,
            );
            let data = tableRows.value.find(
              item => item[mappingProps.rowKey] === rowkey,
            );
            // 新增的直接删除 已有的设置为待删除状态
            if (index >= 0) {
              if (
                data._$changeset &&
                data._$changeset.ChangeType == changeTypeMapping['Add']
              ) {
                let d = tableRows.value.splice(index, 1);
                deleteData.push(d);
              } else {
                changeSet.key = data[mappingProps.rowKey];
                data._$changeset = changeSet;
                data._selected = false;
                deleteData.push(data);
              }
            }
          }
        }

        //触发表格列change事件
        emit('rowsChanged', deleteData, 'deleteEvent');
      }
    };
    const upRowByIndex = index => {
      if (index > 0) {
        //交换位置时避免触发行变更事件
        tableRows.value[index].isChangeing = true;
        tableRows.value[index - 1].isChangeing = true;

        [tableRows.value[index], tableRows.value[index - 1]] = [
          tableRows.value[index - 1],
          tableRows.value[index],
        ];

        nextTick(() => {
          tableRows.value[index].isChangeing = false;
          tableRows.value[index - 1].isChangeing = false;
        });
      }
    };
    const downRowByIndex = index => {
      const lastIndex = tableRows.value.length - 1;
      if (index < lastIndex) {
        //交换位置时避免触发行变更事件
        tableRows.value[index].isChangeing = true;
        tableRows.value[index + 1].isChangeing = true;

        [tableRows.value[index], tableRows.value[index + 1]] = [
          tableRows.value[index + 1],
          tableRows.value[index],
        ];

        nextTick(() => {
          tableRows.value[index].isChangeing = false;
          tableRows.value[index + 1].isChangeing = false;
        });
      }
    };
    //行的值进行了修改
    const rowChange = (data, key) => {
      if (!hasInit) {
        return;
      }
      //标记数据，供外层手动获取数据调用cdo时使用,因此不仅限于数据源类型是cdo的了
      // if (mappingProps.dsType === 'cdo' && mappingProps.dsCDO) {
      //如果绑定了cdo，则要对修改的行进行标注，方便保存时传参
      let orignRowData = orignRows.find(oitem => {
        return oitem[mappingProps.rowKey] === data.row[mappingProps.rowKey];
      });
      if (orignRowData) {
        let changeSet = {
          key: orignRowData[mappingProps.rowKey],
          ChangeTypeName: 'Update',
          ChangeType: changeTypeMapping['Update'],
          ChangeSetItems: [],
        };
        Object.entries(orignRowData).forEach(([key, val]) => {
          if (
            key != '_$changeset' &&
            key != '_selected' &&
            val != data.row[key] &&
            key != 'LastModifyTime'
          ) {
            changeSet.ChangeSetItems.push({
              ColumnCode: key,
              InitValue: val,
              OldValue: val,
              NewValue: data.row[key],
            });
          }
        });
        if (changeSet.ChangeSetItems.length === 0) {
          data.row._$changeset = null;
        } else {
          data.row._$changeset = changeSet;
        }
      }
      // }
      //触发表格列change事件
      emit('rowsChanged', data, key);
    };
    const rowClick = (columnField, rowIndex, rowData) => {
      currentClickRowData = cloneDeep({ columnField, rowIndex, rowData });
      emit('currentRowClick', currentClickRowData);
    };

    const onCurrentData = data => {
      mappingExpose.colCurrentData = {
        data: data,
      };
    };

    //编辑控件的实例进行保存
    const componetsRef = {};
    const rowRef = (key, val) => {
      componetsRef[key] = val;
    };
    // checkbox选择事件
    const onSingleCheck = data => {
      // 单选模式
      let emitData = {};
      if (mappingProps.selection === 'single') {
        for (let i = 0; i < tableRows.value.length; i++) {
          if (i != data.rowIndex) {
            tableRows.value[i]._selected = false;
          }
        }
        emitData.rowIndex = data.rowIndex;
        emitData.value = tableRows.value[data.rowIndex]._selected;
        emitData.data = tableRows.value[data.rowIndex];
      }
      // 多选模式
      if (mappingProps.selection === 'multiple') {
        let isAllChecked = tableRows.value.every(item => {
          return item._selected === true;
        });
        let isNoChecked = tableRows.value.every(item => {
          return item._selected === false;
        });
        if (isAllChecked) {
          allChecked.value = true;
        }
        if (isNoChecked) {
          allChecked.value = false;
        }
        if (!isAllChecked && !isNoChecked) {
          allChecked.value = undefined;
        }

        emitData.value = tableRows.value.filter(
          item => item._selected === true,
        );
        emitData.rowIndex = tableRows.value
          .map((item, index) => {
            if (item._selected === true) {
              return index;
            }
          })
          .filter(elm => elm !== undefined);
      }
      nextTick(() => {
        emit('selectionChanged', emitData);
      });
    };
    //触发选择事件
    const allCheckMethod = () => {
      nextTick(() => {
        let emitData = {
          value: tableRows.value.filter(item => item._selected === true),
          rowIndex: tableRows.value
            .map((item, index) => {
              if (item._selected === true) {
                return index;
              }
            })
            .filter(elm => elm !== undefined),
        };
        emit('selectionChanged', emitData);
      });
    };
    // 预制按钮组点击
    const btnGroupItemClick = item => {
      switch (item.value) {
        case 'add':
          addRows();
          break;
        case 'delete':
          let dataArray = getSelectedTableData();
          if (dataArray && dataArray.length > 0) {
            Funcs.Confirm(
              $q.lang.editTable?.tips,
              $q.lang.editTable?.deleteConfirm,
              async () => {
                if (mappingProps.dsType === 'cdo' && mappingProps.dsCDO) {
                  //删除时如果是cdo模式，直接删除
                  cdoDeleteMethod(dataArray);
                } else {
                  let idsToDelete = dataArray.map(
                    item => item[mappingProps.rowKey],
                  );
                  deleteRowByIndex(idsToDelete);
                }
                allChecked.value = false;
              },
              () => {},
              true,
              { type: 'warning' },
            );
          } else {
            Funcs.Notify(
              $q.lang.editTable?.tips,
              $q.lang.editTable?.deleteRow,
              'warning',
            );
          }
          break;
        case 'save':
          tableSave();
          break;
        case 'reset':
          tableReset();
          break;
      }
    };
    //操作列操作按钮点击
    const outBtnClick = item => {
      emit('actions', item);
    };
    //计算表格高度
    const h = computed(() => {
      const {
        getScrollTarget,
        getVerticalScrollPosition,
        setVerticalScrollPosition,
      } = scroll;
      let scrollTargetDomElement = getScrollTarget(window.body);
      let os = getVerticalScrollPosition(scrollTargetDomElement);
      let top = refComponent.value?.$el
        ? dom.offset(refComponent.value?.$el).top
        : 0;

      if (props.isDev) {
        let designPage = document.querySelector('#app > div.design-page');
        if (designPage && designPage.scrollTop) {
          top += designPage.scrollTop;
        }
      } else {
        if (document.scrollingElement.scrollTop > 0) {
          top += document.scrollingElement.scrollTop;
        }
      }

      return $q.screen.height - top;
    });
    const height = computed(() => {
      let isAuto =
        props.fillMode == 'auto' ||
        ['auto', 'fill'].includes((props.height || '').trim().toLowerCase());
      let mb = props.fillMarginBottom || '0px';
      let hValue = h.value <= 0 ? props.height || undefined : h.value;
      return isAuto
        ? `calc(${hValue - parseInt(mb)}px)`
        : props.height || 'auto';
    });
    function refreshHeaderLayout(target) {
      const thSelector = 'table > thead > tr > th';
      let ths = target.querySelectorAll(thSelector);

      if (0 === ths.length) {
        return;
      }
      const { height, width, style, css } = dom;

      for (var i = 0; i < ths.length; i++) {
        let th = ths[i];
        if (th.width) {
          const wTh = th.width;
          css(th, { width: wTh, minWidth: wTh, maxWidth: wTh });
        } else {
          const wTh = style(th, 'width');
          th.width = wTh;
          css(th, { width: wTh, minWidth: wTh, maxWidth: wTh });
        }
      }
    }
    //列宽调整方法，copy自data-grid
    let localTd = null;
    function mouseDown(e) {
      // 记录单元格
      if (!(e && e.target)) return;
      e.preventDefault();
      e.stopPropagation();
      e.stopImmediatePropagation();
      localTd = e.target;
      localTd.isColMove = false;
      if (e.offsetX > localTd.offsetWidth - 10) {
        localTd.mouseDown = true;
        localTd.oldX = e.x;
        localTd.oldWidth = localTd.offsetWidth;
        if (initSort == true) {
          dragSortModel.value = true;
          mappingProps.allowSort = false;
        }
      }
    }
    // 新增全局鼠标松开处理
    const globalMouseUp = () => {
      if (localTd) {
        localTd.mouseDown = false;
        localTd.isColMove = false;
      }
    };
    function mouseMove(e) {
      if (!(e && e.target)) return;
      e.preventDefault();
      e.stopPropagation();
      e.stopImmediatePropagation();
      const vm = e.target;
      // 更改鼠标样式

      if (vm.tagName != 'TH') {
        return;
      }

      if (e.offsetX > vm.offsetWidth - 10) {
        vm.style.cursor = 'col-resize';
        vm.isColMove = true;
      } else {
        vm.style.cursor = 'default';
      }

      // console.log('mouseMove', e.offsetX, vm.offsetWidth, e.offsetX > vm.offsetWidth - 10, vm.style.cursor, vm)

      // 取出暂存的Table Cell
      if (!localTd) localTd = vm;
      if (localTd.mouseDown !== null && localTd.mouseDown === true) {
        localTd.style.cursor = 'default';
        if (localTd.oldWidth + (e.x - localTd.oldX) > 0) {
          // localTd.width = localTd.oldWidth + (e.x - localTd.oldX);
          localTd.width = localTd.oldWidth + (e.x - localTd.oldX);
          localTd.style.maxWidth =
            localTd.style.minWidth =
            localTd.style.width =
              `${localTd.width}px`;
        }
        // 调整列宽
        localTd.style.maxWidth =
          localTd.style.minWidth =
          localTd.style.width =
            localTd.width;
        localTd.style.cursor = 'col-resize';

        let rect = localTd.getBoundingClientRect();
        if (rect.width != localTd.width) {
          // localTd.style.cursor = 'no-drop';
        }
        setFixedColumn();
        // 调整该列中的每个Cell
        let table = localTd;
        // while (table.tagName !== 'TABLE') table = table.parentElement;
        // for (let j = 0; j < table.rows.length; j++) {
        //   table.rows[j].cells[localTd.cellIndex].width = localTd.width;
        // }
      }
    }
    function mouseUp(e, col) {
      // 结束宽度调整
      if (!(e && e.target)) return;
      e.preventDefault();
      e.stopPropagation();
      e.stopImmediatePropagation();

      if (!localTd) localTd = e.target;
      localTd.mouseDown = false;
      localTd.style.cursor = 'default';

      let dField = localTd.getAttribute('data-field');
      if (dField && col && e.button == 0) {
        // setTimeout(() => {
        //   /** 等待排序逻辑一并提交 */
        //   emitUpdateAdvQueryWithUserProfile();
        // }, 10);
      }
      if (initSort == true && !mappingProps.allowSort) {
        setTimeout(() => {
          mappingProps.allowSort = true;
          dragSortModel.value = false;
        }, 10);
      }
    }
    const setFixedColumnShadow = root => {
      root.querySelectorAll('.q-table tr').forEach(tr => {
        let fixedLeft = tr.querySelectorAll('.fixed-column-left');
        fixedLeft &&
          fixedLeft.length > 0 &&
          fixedLeft[fixedLeft.length - 1].classList.add(
            'fixed-column-left-shadow',
          );

        let fixedRight = tr.querySelectorAll('.sticky.right');
        fixedRight &&
          fixedRight.length > 0 &&
          fixedRight[0].classList.add('fixed-column-right-shadow');
      });
    };

    const setFixedColumn = () => {
      if (props.disableFixedColumn) {
        return;
      }

      let root = refRoot.value;
      if (root) {
        let { left, right } = root.getBoundingClientRect();
        let scrollLeft =
          root.querySelectorAll('.q-virtual-scroll')[0].scrollLeft;
        let scrollRight =
          root.querySelectorAll('.q-virtual-scroll')[0].scrollLeft;
        let s = [];
        root.querySelectorAll('th.fixed-column-left').forEach(col => {
          let colLeft = col.getBoundingClientRect().left + scrollLeft - left;
          let colMinWidth = col.getBoundingClientRect().width;
          if (colMinWidth == 0) {
            return;
          }
          if (s.length > 0) {
            colLeft = s[s.length - 1].left + s[s.length - 1].minWidth;
          }
          s.push({ left: colLeft, minWidth: colMinWidth });
          if (!col.style.left) {
            col.style.left = colLeft + 'px';
            col.style.maxWidth = col.style.minWidth = colMinWidth + 'px';
          }
          // col.style.left = colLeft + "px";
          // col.style.maxWidth = col.style.minWidth = colMinWidth + "px";
        });
        let sCount = s.length;
        let sIndex = 0;

        root.querySelectorAll('tbody tr').forEach(tr => {
          tr.querySelectorAll('td.fixed-column-left').forEach(
            (col, colIndex) => {
              if (!col.style.left) {
                col.style.left = s[colIndex]?.left + 'px';
              }
              // col.style.maxWidth = col.style.minWidth = s[colIndex].minWidth + "px";
            },
          );
        });

        let rightCols = root.querySelectorAll('.fixed-column-right');
        for (let index = rightCols.length - 1; index >= 0; index--) {
          // const element = array[index];
          let col = rightCols[index];
          col.style.right =
            right + scrollLeft - col.getBoundingClientRect().right + 'px';
        }
        setFixedColumnShadow(root);
      }
    };

    const setFixedColumnByMousemove = () => {
      if (props.disableFixedColumn) {
        return;
      }

      let root = refRoot.value;
      if (root) {
        let s = [];
        root.querySelectorAll('th.fixed-column-left').forEach(col => {
          s.push({ left: col.style.left, minWidth: col.style.minWidth });
        });
        let sCount = s.length;
        let sIndex = 0;

        root.querySelectorAll('tbody tr').forEach(tr => {
          tr.querySelectorAll('td.fixed-column-left').forEach(
            (col, colIndex) => {
              col.style.left = s[colIndex].left;
            },
          );
        });
        setFixedColumnShadow(root);
      }
    };

    return () => {
      return (
        <div
          ref={refRoot}
          tabIndex={props.tabIndex == undefined ? 1 : props.tabIndex}
          class='no-outline'
        >
          {/* 顶部按钮 */}
          <TBtnGroup
            v-show={mappingProps.enableEditing && mappingProps.visible}
            class='tr-editTable-btnGroup'
            ref='tableBtngroup'
            staticItems={[
              {
                label: $q.lang.editTable?.addRow
                  ? $q.lang.editTable.addRow
                  : '新增',
                value: 'add',
                icon: 'icon-t-plus',
                type: 'primary',
                visible: mappingProps.topBtnOption.includes('1'),
                hint: $q.lang.editTable?.addRow
                  ? $q.lang.editTable.addRow
                  : '新增',
              },
              {
                label: $q.lang.editTable?.deleteRows
                  ? $q.lang.editTable.deleteRows
                  : '删除',
                value: 'delete',
                icon: 'icon-t-minus',
                type: 'default',
                visible: mappingProps.topBtnOption.includes('2'),
                hint: $q.lang.editTable?.deleteRows
                  ? $q.lang.editTable.deleteRows
                  : '删除',
              },
              {
                label: $q.lang.editTable?.save
                  ? $q.lang.editTable.save
                  : '保存',
                value: 'save',
                icon: 'icon-t-save',
                type: 'default',
                visible: mappingProps.topBtnOption.includes('3'),
                hint: $q.lang.editTable?.save ? $q.lang.editTable.save : '保存',
              },
              {
                label: $q.lang.editTable?.reset
                  ? $q.lang.editTable.reset
                  : '取消',
                value: 'reset',
                icon: 'icon-t-redo',
                type: 'default',
                visible: mappingProps.topBtnOption.includes('4'),
                hint: $q.lang.editTable?.reset
                  ? $q.lang.editTable.reset
                  : '取消',
              },
            ]}
            btnSpace='8px'
            onBtnGroupItemClick={btnGroupItemClick}
            tabIndex='1'
            style='width:100%; justify-content: flex-end;margin-bottom:8px;'
          />

          <Component
            ref={refComponent}
            {...attrs}
            {...pickOwnForBasicComponent(mappingProps, Component.props, attrs)}
            class={['tr-edit-table', styles.module]}
            class={{
              tdfixed: mappingProps.operationColumnFixed,
            }}
            tabIndex={attrs.tabIndex == undefined ? -1 : attrs.tabIndex}
            v-show={mappingProps.visible}
            rows={tableRows.value}
            columns={tableColumns.value}
            pagination={{
              rowsPerPage: 0,
            }}
            virtual-scroll={mappingProps.virtualScroll}
            hide-pagination
            style={{
              'height': height.value,
              'max-height': height.value,
            }}
          >
            {{
              'header': props => {
                return (
                  <QTr props={props}>
                    {props.cols.map((item, columnIndex) => {
                      return (
                        <QTh
                          key={item.name}
                          props={props}
                          class={{
                            thfixed: mappingProps.fillMode == 'custom',
                          }}
                          style={{
                            'text-align': item.align ? item.align : 'left',
                            'width': item.width
                              ? parseFloat(item.width) + 'px'
                              : '',
                          }}
                          onMousedown={mouseDown}
                          onMousemove={
                            mappingProps.allowColumnResizing && mouseMove
                          }
                          onMouseup={e => {
                            mouseUp(e, props.col);
                          }}
                        >
                          {item.name === '_selected' &&
                          item.editorType === 'checkbox' &&
                          mappingProps.selection === 'multiple' ? (
                            <TCheckbox
                              v-model={allChecked.value}
                              onUpdate:modelValue={allCheckMethod}
                            />
                          ) : (
                            <span>
                              {item.label}
                              <i
                                class='fas dx-icon icon-t-question-circle header-tips'
                                style='margin-left:4px;color:rgba(0,0,0,.56)'
                                v-show={item.description}
                              >
                                <Tooltip>{item.description}</Tooltip>
                              </i>
                              <span
                                style='margin-left:4px;color:red'
                                v-show={
                                  item.isRequired == 'true' ||
                                  item.isRequired == true
                                }
                              >
                                *
                              </span>
                            </span>
                          )}
                        </QTh>
                      );
                    })}
                  </QTr>
                );
              },
              'body': props => {
                if (props.row?._$changeset?.ChangeTypeName === 'Delete') {
                  return undefined;
                }
                return (
                  <TableContent
                    ref={TableContentRef}
                    parentProps={mappingProps}
                    tableProps={props}
                    columns={tableColumns.value}
                    onSingleCheck={onSingleCheck}
                    onOutBtnClick={outBtnClick}
                    onUpRowByIndex={upRowByIndex}
                    onDownRowByIndex={downRowByIndex}
                    onRowChange={rowChange}
                    onRowRef={rowRef}
                    onDivRowClick={rowClick}
                    onCurrentData={onCurrentData}
                  />
                );
              },
              'no-data': (message, icon) => (
                <div
                  style={{
                    'width': '100%',
                    'inset': '0px',
                    'display': 'flex',
                    'justify-content': 'center',
                    'align-items': 'center',
                    'height': `calc(${height.value} - 100px)`,
                  }}
                >
                  <NoDataPlaceholder
                    text={$q.lang.dataGrid?.emptyText}
                  ></NoDataPlaceholder>
                </div>
              ),
              'loading': () => <TInnerLoading showing color='var(--t-color)' />,
            }}
          </Component>
        </div>
      );
    };
  },
});
